﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Media;
using Caliburn.Core.InversionOfControl;
using Caliburn.PresentationFramework.Invocation;
using Caliburn.PresentationFramework.RoutedMessaging;
using Caliburn.ShellFramework.Results;
using MTGenome.MTG;
using MTGenome.UI;

namespace MTGenome.ViewModels
{
    [Singleton(typeof(CardDetailViewModel)), PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class CardDetailViewModel : RescueBase
    {
        private static readonly ImageSource _blankCard = ImageLoader.Load("pack://application:,,,/Embed/BlankCard.jpg");

        private readonly IGathererServer _gatherer;
        private ICard _card = null;
        private ImageSource _expansion = null,
            _image = null;
        private CardInlineViewModel[] _text = null;

        public CardDetailViewModel(IGathererServer gatherer)
        {
            _gatherer = gatherer;
        }

        public ICard Card
        {
            get { return _card; }
            set
            {
                if (_card != value)
                {
                    _card = value;
                    OnCardChanged();
                }
            }
        }

        public bool HasCard
        {
            get { return _card != null; }
        }

        public ImageSource Image
        {
            get { return _image; }
        }

        public string Name
        {
            get { return _card == null ? null : _card.Name; }
        }

        public bool HasManaCost
        {
            get { return _card == null ? false : !string.IsNullOrEmpty(ManaCost); }
        }

        public string ManaCost
        {
            get { return _card == null ? null : _card.ManaCost; }
        }

        public byte? ConvertedManaCost
        {
            get { return _card == null ? default(byte?) : _card.ConvertedManaCost; }
        }

        public string Type
        {
            get { return _card == null ? null : _card.Type; }
        }

        public CardInlineViewModel[] Text
        {
            get { return _text; }
        }

        public bool HasFlavorText
        {
            get { return _card == null ? false : !string.IsNullOrEmpty(FlavorText); }
        }

        public string FlavorText
        {
            get { return _card == null ? null : _card.FlavorText; }
        }

        public string Artist
        {
            get { return _card == null ? null : _card.Artist; }
        }

        public string Rarity
        {
            get { return _card == null ? string.Empty : _card.Rarity == MTG.Rarity.MythicRare ? "Mythic Rare" : _card.Rarity.ToString(); }
        }

        public string ExpansionText
        {
            get { return _card == null ? null : "(" + _card.Expansion + ") " + _card.ExpansionName; }
        }

        public ImageSource Expansion
        {
            get { return _expansion; }
        }

        private void OnCardChanged()
        {
            _image = _blankCard;
            _expansion = null;
            if (_card != null)
            {
                int index = 0;
                _text = _card.Text
                    .Split('[', ']')
                    .Select(t => new CardInlineViewModel(t, (index++ % 2) == 1))
                    .Where(c => !string.IsNullOrEmpty(c.Text))
                    .ToArray();
                LoadImages();
            }
            NotifyOfPropertyChange(() => HasCard);
            NotifyOfPropertyChange(() => Image);
            NotifyOfPropertyChange(() => Name);
            NotifyOfPropertyChange(() => Type);
            NotifyOfPropertyChange(() => HasManaCost);
            NotifyOfPropertyChange(() => ManaCost);
            NotifyOfPropertyChange(() => ConvertedManaCost);
            NotifyOfPropertyChange(() => Text);
            NotifyOfPropertyChange(() => HasFlavorText);
            NotifyOfPropertyChange(() => FlavorText);
            NotifyOfPropertyChange(() => Rarity);
            NotifyOfPropertyChange(() => Expansion);
            NotifyOfPropertyChange(() => ExpansionText);
            NotifyOfPropertyChange(() => Artist);
            NotifyOfPropertyChange(() => Card);
        }

        private void LoadImages()
        {
            ICard obj1 = _card;
            Execute.OnBackgroundThread(() =>
            {
                string path = null;
                try
                {
                    ICard card = obj1;
                    path = _gatherer.GetImagePath(_card.Expansion, _card.Rarity, ImageSize.Small);
                    if (string.IsNullOrEmpty(path))
                    {
                        return;
                    }

                    Execute.OnUIThread(() =>
                    {
                        if (card == _card)
                        {
                            _expansion = ImageLoader.Load(path);
                            NotifyOfPropertyChange(() => Expansion);
                        }
                    });
                }
                catch (Exception exc)
                {
                    Console.WriteLine("Error with Image: {0} {1}", System.IO.Path.GetFileName(path), exc.Message);
                }
            });
            ICard obj2 = _card;
            Execute.OnBackgroundThread(() =>
            {
                string path = null;
                try
                {
                    ICard card = obj2;
                    path = _gatherer.GetImagePath(_card.MultiverseID);
                    if (string.IsNullOrEmpty(path))
                    {
                        return;
                    }

                    Execute.OnUIThread(() =>
                    {
                        if (card == _card)
                        {
                            _image = ImageLoader.Load(path, 223, 310);
                            NotifyOfPropertyChange(() => Image);
                        }
                    });
                }
                catch (Exception exc)
                {
                    Console.WriteLine("Error with Image: {0} {1}", System.IO.Path.GetFileName(path), exc.Message);
                }
            });
        }
    }
}
